define(['jquery','jquerymobile','presenter','utils','require'],function($, jqm, presenter, utils, require) {
    console.log("view loaded");
    
    var houseworkList = [];
    var locationTrackList = [];
    var currentFileList = [];
    var currentDirName = '';
    var selectedFileItem;
    var selectedHouseworkId = 0;
    var optionMap = {
        '#max-temp-input' : 'environment.statistics.maxtemp',
        '#heat-alert-check' : 'environment.statistics.maxtemp.isalert',
        '#min-temp-input' : 'environment.statistics.mintemp',
        '#low-temperature-check' : 'environment.statistics.mintemp.isalert',
        '#brightness-alert-check' : 'environment.statistics.brightness.isalert',
        '#fire-alert-check' : 'environment.statistics.firesafety.isalert',
        '#pi-health-alert-check' : 'system.pihealth.isalert',
        '#user-locationtrack-toggle': 'system.usercenter.istrackme',
        '#is-living-in-china-toggle': 'system.usercenter.isinchina',
        '#vibrate-notification-toggle': 'system.usercenter.isvibratewhennotifying',
        '#location-track-interval-select': 'system.usercenter.locationreportinterval',
        '#remember-login-toggle': 'system.usercenter.donotrememberlogin',
    };
    var simpleSexMap = {
        1: 'M',
        0: 'F'
    };
    var fullSexMap = {
        1: 'Male',
        0: 'Female'
    };
    var checkableUI = [
        '#heat-alert-check', 
        '#low-temperature-check', 
        '#brightness-alert-check', 
        '#fire-alert-check', 
        '#pi-health-alert-check', 
        '#user-locationtrack-toggle', 
        '#is-living-in-china-toggle', 
        '#vibrate-notification-toggle',
        '#remember-login-toggle',
    ];
    var currentUser = undefined;
    var selectedMemberId = 0;
    var task;
    
    // Hash route handler
    $(window).hashchange(function() {
        var hash = location.hash;
        console.log("hash: " + hash);

        // Check if authenticated
        if (!isAuthenticated()) {
            console.error("You're not authenticated!");
            utils.navigateTo('#login');
        }

        if (hash === '#data-now') {
            utils.showLoader();
            presenter.getCurrentHomeEnvironmentData(populateHomeData);
        }
        else if (hash === '#housework') {
            var user; 

            utils.showLoader();
            // 0 means get all users, only if the current user is admin
            if (0 === currentUser.role) {
                presenter.getUserList(populateUserList);
                user = 0;
            }
            else {
                // Hide the user select since we don't need it if the user is not admin
                $('#username-button').addClass("hidden-block");
                $('button#detail-action-btn').addClass("hidden-block");
                $('#add-new-housework-btn').addClass("hidden-block");
                user = currentUser.id;
            }
            presenter.getHouseworkListByUser(user, populateHouseworkList);
        }
        else if (hash === "#housework-create") {
            utils.showLoader();
            presenter.getUserList(populateUsersForHouseworkCreation);
        }
        else if (hash === "#statistics") {
            utils.showLoader();
            presenter.getTodayTemperatureList("graph", showTemperatureStatsImg);
            presenter.getAbnormalBrightnessList(populateBrightnessList);
            presenter.getAbnormalFiresafetyList(populateFiresafetyList);
        }
        else if (hash === "#sugar-statistic") {
            utils.showLoader();
            presenter.getBloodSugarListByUser(populateSugarHistory);
            presenter.getBloodSugarStatsInToday(showBloodSugarStatsImg);
        }
        else if (hash === "#location-track") {
            utils.showLoader();
            presenter.getAllUsersLocationRecordList(populateLocationTrackListview);
        }
        else if (hash === "#user-detail") {
            populateUserDetails(currentUser);
        }
        else if (hash === "#user-center") {
            presenter.getMyselfInfo(populateMyselfInfo);
        }
        else if (hash === "#my-family") {
            presenter.getUserList(populateUserListview);
        }
        else if (hash === "#my-files") {
            utils.showLoader();
            presenter.getFileList('', populateFileListview);
        }
    });
    // End of Hash route handler

    // Event Listeners
    // Page container event listener
    $('body').on('pagecontainershow', function (event, ui) {
        var pageId = getCurrentPageId();

        if ('user-detail-birthday-edit-action' === pageId) {
            $('#user-birthday-action-input').datebox('setTheDate', currentUser.birth)
                                            .datebox('refresh');
        }
    });

    $('body').on('pagecontainertransition', function (event, ui) {
        var pageId = getCurrentPageId();
        var path = ui.absUrl;
        var paramsMap = getParamsMapFromUrl(path);

        // Edit user's property (name and email)
        if ('user-detail-edit-action' === pageId) {
            var type = paramsMap['type'];
            var confirmSelector = $('#user-detail-update-confirm');
            var setConfirmBtnListener = function (type) {
                confirmSelector.click(function () {
                    var value = $('#user-detail-edit-action input#user-action-input').val();

                    presenter.updateMyselfInfo(type, value, function () {
                        // Update currentUser object
                        eval('currentUser.' + type +  '= value');
                        utils.navigateTo('#user-detail');
                    });
                });
            };

            // Remove previously bound event listener
            confirmSelector.unbind('click');
            setConfirmBtnListener(type);
        }
    });
    // End of Page container event listener

    // Login event handler
    $('#begin-login-btn').click(function (event) {
        var username = $('#login-username-input').val();
        var password = $('#login-password-input').val();
        var serverUrl = localStorage.getItem('url');

        if (utils.isStrEmpty(username)) {
            utils.showToast('Username should not be empty.', 'short', 'bottom');
            return;
        }

        if (utils.isStrEmpty(password)) {
            utils.showToast('Password should not be empty.', 'short', 'bottom');
            return;
        }

        if (utils.isStrEmpty(serverUrl)) {
            utils.showToast('Unknown host: ' + serverUrl, 'short', 'bottom');
            return;
        }
        
        utils.appConfig().serverHost(serverUrl);

        presenter.userLogin(username, password, function(result) {
            var resultCode = result.resultCode;
            var accessToken = result.token;

            if (1 === resultCode) {
                utils.appConfig().accessTokenValue(accessToken);
                utils.appConfig().userName(username);
                utils.appConfig().userPassword(password);

                currentUser = result.user;
                // Hidden admin only leftpanel entries
                if (0 != result.user.role) 
                    hiddenAdminOnlyEntries();

                initApp();

                if (localStorage.getItem('system.usercenter.donotrememberlogin') === 'true') {
                    localStorage.removeItem('username');
                    localStorage.removeItem('password');
                }
                else {
                    localStorage.setItem('username', username);
                    localStorage.setItem('password', password);
                }
                utils.navigateTo('#my-files');
            }
            else if (0 === resultCode) {
                utils.showToast("Wrong username or password.", 'short', 'bottom');
            }
            else {
                utils.showToast("Bad login.", 'short', 'bottom');
            }
        });

    });    

    $('#config-login-btn').click(function (event) {
        var defaultServer = localStorage.getItem('url');
        var remoteServer = prompt('Pi server address', null === defaultServer ? '' : defaultServer);

        if (!utils.isStrEmpty(remoteServer)) {
            utils.appConfig().serverHost(remoteServer);
            localStorage.setItem('url', remoteServer);
        }
    });
    // End of Login event handler

    // Housework event listener
    $('#housework-listview').on('click','li',function() {
        var index = $(this).index();
        var houseworkItem = houseworkList[index];
        
        selectedHouseworkId = houseworkItem.id;
        $("#housework-detail-listview li:nth-child(1) img").attr('src', getImageUrl() + "/images/" + houseworkItem.avatar);
        $("#housework-detail-listview li:nth-child(1) h2").text(houseworkItem.user_name);
        $("#housework-detail-listview li:nth-child(1) p").text(houseworkItem.time);
        $('#housework-detail-listview li:nth-child(2)').html("<h2>Task:</h2> " + houseworkItem.task);
        $('#housework-detail-listview li:nth-child(3)').html("<h2>Reward:</h2> " + houseworkItem.reward);
        $('button#detail-action-btn').text(houseworkItem.status === 1 ? "Completed" : "Doing...")
                                     .removeClass('ui-icon-check ui-icon-clock')
                                     .addClass(houseworkItem.status === 1 ? 'ui-btn-icon-left ui-icon-check' : 'ui-btn-icon-left ui-icon-clock');
        utils.navigateTo('#housework-detail');
    });

    $('button#housework-create-confirm-btn').click(function() {
        var user = $("select#selectable-username").val();

        if (parseInt(user) < 1) {
            utils.showToast("Please choose one person!", 'short', 'bottom');
            return;
        }

        var isContinue = confirm("Add this new task?");
        if (!isContinue)
            return;

        var task = $("input#task-input").val().trim();
        var reward = $("input#reward-input").val().trim();
       
        utils.showLoader();
        presenter.addNewTask(user, task, reward, function(resultCode) {
            if (resultCode === 1) {
                utils.showToast("Add new task successfully!", 'short', 'bottom');
                utils.navigateTo('#housework');

                $("select#selectable-username").val(1);
                $("select#selectable-username").trigger("change");
                $("input#task-input").val("");
                $("input#reward-input").val("");
            }
            else {
                alert("Failed to add this new task!");
            }
            utils.hideLoader();
        });

    });

    $('button#detail-action-btn').click(function() {
        if ($(this).text() === "Completed")
            return;
        var isContinue = confirm("Flag this task as Completed?");

        if (isContinue) {
            presenter.markTaskCompleted(selectedHouseworkId, function(resultCode) {
                if (resultCode === 1) {
                    utils.showToast("Task Updated Successfully!", 'short', 'bottom');
                    $('button#detail-action-btn').removeClass('ui-icon-check ui-icon-clock')
                                                 .addClass('ui-icon-check')
                                                 .text("Completed");
                }
                else {
                    alert("Failed to Update Task!");
                }
            });
        }
    });

    $("select#username").change(function() {
        var user = $("select#username").val();
        presenter.getHouseworkListByUser(user, populateHouseworkList);
    });
    // End of Housework event listener

    $('ul#location-thumbnail-listview').on('click', 'li', function() {
        var index = $(this).index();
        var locationItem = locationTrackList[index];
        
        presenter.getLocationRecordListForUser(locationItem.user_id, populateLocationDetailListview);
    });


    // Sugar event listener
    $('button#sugar-confirm-btn').click(function() {
        var date = $('input#add-date').val();
        var time = utils.parseTo24HourFormat($('input#add-time').val());
        var tag = $('select#add-tag').val();
        var value = $('input#sugar-value').val().trim();

        if (value.trim() === '') {
            utils.showToast("Please input your blood sugar value.", 'short', 'bottom');
            return;
        }

        var isContinue = confirm("Add this new Blood Sugar record?");
        if (!isContinue)
            return;

        utils.showLoader();
        presenter.createNewSugarItem(date, time, tag, value, function(resultCode) {
            if (resultCode === 1) {
                utils.showToast("Add new Blood Sugar record successfully!", 'short', 'bottom');
                utils.navigateTo('#sugar-statistic');
                $('input#sugar-value').val('');
            }
            else {
                alert("Failed to add new Blood Sugar record!");
            }
            utils.hideLoader();
        });
    });
    // End of Sugar event listener

    // My Files event listener
    $("#file-upload-btn").click(function() {
        presenter.uploadMyFile(currentDirName,
                               function(res) {
                                utils.showToast("Upload File Succeeds.", 'short', 'bottom');
                                utils.hideLoader();
                                presenter.getFileList(currentDirName, populateFileListview);
                               },
                               function(error) {
                                utils.hideLoader();
                                alert("Failed to upload: " + error.code + " " + error.source + " " + error.target);
                               }
                               );
    });

    $("#add-dir-btn").click(function() {
        var newFolderName = $("#dirname-input").val();

        if (utils.isStrEmpty(newFolderName)) {
            utils.showToast("Folder name is invalid!", 'short', 'bottom');
            return;
        }

        newFolderName = newFolderName.trim();

        utils.showLoader();
        presenter.createNewFolder(
                                    currentDirName, 
                                    newFolderName, 
                                    function(resultCode) {
                                        if (1 === resultCode) {
                                            utils.showToast("New folder creation succeeds.", 'short', 'bottom');
                                            presenter.getFileList(currentDirName, populateFileListview);
                                            $("#add-dir-popup").popup("close");
                                            $("#dirname-input").val("");
                                            selectedFileItem = undefined;
                                        }
                                        else {
                                            alert("Folder creation failed! Please check your network availability.");
                                        }
                                    }
                                 );
    });

    $("#delete-myfile-btn").click(function() {
        if (undefined == selectedFileItem) {
            utils.showToast("Please select one file.", 'short', 'bottom');
            return;
        }
        
        var warnningText = (0 === selectedFileItem.type) ? 
                            "Be cautious! All files in this folder will be lost!" :
                            "Do you really want to delete this file?";
        var isContinue = confirm(warnningText);

        if (isContinue) {
            utils.showLoader();
            presenter.removeFile(
                                    currentDirName, 
                                    selectedFileItem.name, 
                                    function(resultCode) {
                                        if (1 === resultCode) {
                                            utils.showToast("Deletion completed.", 'short', 'bottom');
                                            presenter.getFileList(currentDirName, populateFileListview);
                                            selectedFileItem = undefined;
                                        }
                                        else {
                                            alert("Failed to delete it!");
                                        }
                                    }
                                );
        }
    });

    $("#start-edit-filename-btn").click(function(event) {
        if (undefined == selectedFileItem) {
            utils.showToast("Please select one file.", 'short', 'bottom');
            return;
        }

        $("#edit-filename-popup").popup("open");
    });

    $("#edit-filename-btn").click(function(event) {
        var newFilename = $("#new-filename-input").val();

        if (utils.isStrEmpty(newFilename)) {
            utils.showToast("File name is invalid!", 'short', 'bottom');
            return;
        }

        newFilename = newFilename.trim();
        utils.showLoader();
        presenter.renameFile(
                                currentDirName,
                                selectedFileItem.name,
                                newFilename,
                                function(resultCode) {
                                    if (1 === resultCode) {
                                        utils.showToast("Rename file successfully.", 'short', 'bottom');
                                        $("#edit-filename-popup").popup("close");
                                        $("#new-filename-input").val("");
                                        selectedFileItem = undefined;
                                        presenter.getFileList(currentDirName, populateFileListview);
                                    }
                                    else {
                                        alert("Failed to rename it!");
                                    }
                                }
        );
    });


    $('table#my-files-table').on('click', 'tr', function(event) {
        $(this).addClass('selected').siblings().removeClass('selected');
        selectedFileItem = currentFileList[$(this).index()];
    });
    // End of My Files event listener

    // Contacts Sync event listener
    $('#backup-btn').click(function(event) {
        var isContinue = confirm("Backup your contacts on Raspberry pi?");
        if (!isContinue)
            return;

        utils.showLoader();
        $('#backup-btn').addClass('ui-state-disabled');
        $("#sync-btn").addClass('ui-state-disabled');
        presenter.getAllContactsList(function(contacts) {
            presenter.backupMyContacts(JSON.stringify(contacts), function(resultCode) {
                if (1 === resultCode) {
                    utils.showToast("Backup contacts successfully.", 'short', 'bottom');
                }
                else {
                    alert("Failed to backup contacts!");
                }
                utils.hideLoader();
                $("#sync-btn").removeClass('ui-state-disabled');
                $('#backup-btn').removeClass('ui-state-disabled');
            });
        });
    });

    $("#sync-btn").click(function(event) {
        var warnningText = "Do you really need phone contacts sync?\n" +
                           "In fact, it should be performed only when you buy a new phone and want " +
                           "to load your old contacts at once. If not, don't do this sync, or you will " +
                           "run the risk of duplicating many contacts. Do you still want to proceed?";
        var isContinue = confirm(warnningText);
        if (!isContinue)
            return;
        
        utils.showLoader();
        $("#sync-btn").addClass('ui-state-disabled');
        $('#backup-btn').addClass('ui-state-disabled');
        presenter.syncMyContacts(function(contactsCount) {
            utils.hideLoader();
            $("#sync-btn").removeClass('ui-state-disabled');
            $('#backup-btn').removeClass('ui-state-disabled');
            utils.showToast(contactsCount + " contacts synced.", 'short', 'bottom');
        });
    });
    // End of Contacts Sync event listener
    
    // Home environment stats event listener
    $('#max-temp-input').on('focusout', function () {
        var key = optionMap['#max-temp-input'];
        var value = $(this).val();
        
        saveOption(key, value);
    });

    $('#heat-alert-check').on('change', function () {
        var key = optionMap['#heat-alert-check'];
        var value = "" + $(this).is(":checked");
        
        saveOption(key, value);
    });

    $('#min-temp-input').on('focusout', function () {
        var key = optionMap['#min-temp-input'];
        var value = $(this).val();

        saveOption(key, value);
    });

    $('#low-temperature-check').on('change', function () {
        var key = optionMap['#low-temperature-check'];
        var value = "" + $(this).is(":checked");

        saveOption(key, value);
    });

    $('#brightness-alert-check').on('change', function () {
        var key = optionMap['#brightness-alert-check'];
        var value = "" + $(this).is(":checked");

        saveOption(key, value);
    });

    $('#fire-alert-check').on('change', function () {
        var key = optionMap['#fire-alert-check'];
        var value = "" + $(this).is(":checked");

        saveOption(key, value);
    });
    // End of Home environment event listener

    // Pi Health event listener
    $('#pi-health-alert-check').on('change', function () {
        var key = optionMap['#pi-health-alert-check'];
        var value = "" + $(this).is(":checked");

        saveOption(key, value);
    });
    // End of Pi Health event listener

    // User Center event listener
    $('ul#user-detail-listview, ul#user-noncrtitical-detail-listview')
        .on('vmousedown', 'li', function(event) {
            $(this).addClass('checked-item');
        })
        .on('vmouseup', 'li', function(event) {
            $(this).removeClass('checked-item');
        });
    
    $('#user-center input[type=checkbox]').change(function(event) {
        var id = "#" + $(this).attr('id');
        var checkStatus = $(this).is(':checked');
        
        localStorage.setItem(optionMap[id], checkStatus);
    });

    $('#user-center select').change(function(event) {
        var id = "#" + $(this).attr('id');
        var selectedValue = $(this).val();

        localStorage.setItem(optionMap[id], selectedValue);
    });

    $('li#user-avatar-item').click(function (event) {
        presenter.updateMyAvatar(
                               function(res) {
                                utils.showToast("Avatar update succeeds.", 'short', 'bottom');
                                presenter.getMyselfInfo(function (dataList) {
                                    var mydata = dataList[0];
                                    
                                    currentUser = mydata;
                                    // Update the profile photo
                                    $('div#user-detail ul#user-detail-listview li#user-avatar-item img')
                                        .prop('src', getImageUrl() + '/images/' + currentUser.avatar);

                                    utils.hideLoader();
                                });
                               },
                               function(error) {
                                utils.hideLoader();
                                alert("Failed to update avatar: " + error.code + " " + error.source + " " + error.target);
                               }
        );
    });

    $('li#user-name-item').click(function(event) {
        var userNameSelector = $('#user-detail-edit-action #user-action-input');

        changePageTitle('#user-detail-edit-action', 'My Name');

        userNameSelector.prop('type', 'text');
        userNameSelector.val(currentUser.name);
        utils.navigateTo('#user-detail-edit-action?type=name');
    });

    $('li#user-email-item').click(function(event) {
        var userEmailSelector = $('#user-detail-edit-action #user-action-input');

        changePageTitle('#user-detail-edit-action', 'E-mail');

        userEmailSelector.prop('type', 'email');
        userEmailSelector.val(currentUser.email);

        utils.navigateTo('#user-detail-edit-action?type=email');
    });

    $('li#user-birth-item').click(function(event) {
        utils.navigateTo('#user-detail-birthday-edit-action');
    });

    $('li#user-gender-item').click(function(event) {
       var pop = $('div#gender-update-popup');

       setGenderDetail(0 === currentUser.sex ? 
                       $('#gender-update-popup li#gender-female-item') : 
                       $('#gender-update-popup li#gender-male-item'));

       pop.popup("open");
    });

    $('li#user-password-item').click(function(event) {
        utils.navigateTo('#user-detail-password-edit-action');
    });

    $('#user-detail-password-edit-confirm').click(function(event) {
        var oldPasswordSelector = $('#user-old-password-input');
        var newPasswordSelector = $('#user-new-password-input');
        var newPasswordAgainSelector = $('#user-new-password-again-input');
        var oldPassword = oldPasswordSelector.val();
        var newPassword = newPasswordSelector.val();
        var newPasswordAgain = newPasswordAgainSelector.val();

        if (utils.isStrEmpty(oldPassword)) {
            utils.showToast('Missing current password.', 'short', 'bottom');
            oldPasswordSelector.select();
            return;
        }
        
        if (utils.isStrEmpty(newPassword)) {
            utils.showToast('Missing new password.', 'short', 'bottom');
            newPasswordSelector.select();
            return;
        }

        if (utils.isStrEmpty(newPasswordAgain)) {
            utils.showToast('You need to type your new password again', 'short', 'bottom');
            newPasswordAgainSelector.select();
            return;
        }

        if (newPasswordAgain != newPassword) {
            utils.showToast('Passwords don\'t match', 'short', 'bottom');
            newPasswordAgainSelector.select();
            return;
        }
        
        utils.showLoader();
        presenter.updateUserPassword(oldPassword, newPassword, function (resultCode) {
            if (1 === resultCode) {
                utils.showToast('Update your password successfully.', 'short', 'bottom');
                clearInputTexts(oldPasswordSelector);
                clearInputTexts(newPasswordSelector);
                clearInputTexts(newPasswordAgainSelector);
                utils.navigateTo('#user-detail');
            }
            else {
                alert('Failed to update your password!');
            }
        });
    });

    $('li#user-new-password-again-item input').on('keyup focus', function(event) {
        var outerWrapper = $('li#user-new-password-again-item div');
        var warnningClassName = 'input-warnning';
        var newPasswordInputSelector = $('#user-new-password-input');

        // Add or remove the 'input-warnning' class on the wrapper div of input element 
        // conditionally, so that the color of box-shadow can be changed
        outerWrapper.addClass(warnningClassName);

        // Only if the texts in two inputs are the same can we remove the warnning class
        if ($(this).val() === newPasswordInputSelector.val())
            outerWrapper.removeClass(warnningClassName);

    }).focusout(function(event) {
          $('li#user-new-password-again-item div').removeClass('input-warnning');
    });

    $('div#gender-update-popup').on('click', 'ul li', function() {
        setGenderDetail($(this));

        // Get reverse gender
        var newGender = 1 - currentUser.sex;

        presenter.updateMyselfInfo('sex', newGender, function () {
            $('#user-detail li#user-gender-item span:nth-child(2)').val(newGender);
            currentUser.sex = newGender;
            $('div#gender-update-popup').popup('close');
        });
    });

    $('#user-birthday-action-input').on('datebox', function (e, passed) { 
        var method = passed.method;
        var value = passed.value;

        if (method === 'set' && currentUser.birth !== value) {
            presenter.updateMyselfInfo('birth', value, function () {
                currentUser.birth = value;
                console.log('update birthday to ' + value);
                utils.navigateTo('#user-detail');
            });
        }
    });

    $('#add-new-member-btn').click(function(event) {
        var username = $('#user-add-username-input').val();
        var role = $('#user-add-role-toggle').is(':checked') ? 0 :1;

        presenter.addNewUser(username, role, function (resultCode) {
            if (1 === resultCode) {
                utils.showToast('Add new member successfully.', 'short', 'bottom');
                utils.navigateTo('#my-family');
            }
            else {
                alert('Add new member failed.');
            }
        });
    });

    $('#my-family ul#member-listview').on('taphold', 'li', function(event) {
        selectedMemberId = $(this).attr('user-id');

        $('div#my-family-member-action-popup').popup('open');
    });

    $('#my-family-member-delete-btn').click(function(event) {
        $('div#my-family-member-action-popup').popup('close');

        if (!confirm('Delete this member? The operation is unrecoverable!'))
            return;

        utils.showLoader();
        presenter.removeUser(selectedMemberId, function(resultCode) {
            if (1 === resultCode) {
                presenter.getUserList(populateUserListview);
                console.debug('Delete user successfully.');
            }
            else {
                alert("Failed to delete this member.");
            }
            utils.hideLoader();
        });
    });

    $('#my-family-member-reset-password-btn').click(function(event) {
        $('div#my-family-member-action-popup').popup('close');

        if (!confirm('Reset the password of this member to default one?'))
            return;

        utils.showLoader();
        presenter.resetUserPassword(selectedMemberId, function(resultCode) {
            if (1 === resultCode) {
                utils.showToast("Reset password successfully.", "short", "bottom");
            }
            else {
                alert("Failed to reset password.");
            }
            utils.hideLoader();
        });
    });
    // End of User Center event listener

    // Misc event listener
    $('#logout-btn').click(function() {
       // Stop any timer
       clearTimeout(task);

       // Clear accessToken, userName and userPassword
       utils.appConfig().accessTokenValue('');
       utils.appConfig().userName('');
       utils.appConfig().userPassword('');

       // Restore the hidden entries elements
       restoreToDefaultEntries();
       $('#username-button').removeClass("hidden-block");
       $('button#detail-action-btn').removeClass("hidden-block");
       $('#add-new-housework-btn').removeClass("hidden-block");

       // Go to login page
       utils.navigateTo('#login');
    });

    $('form').submit(function(event) {
        event.preventDefault();
    });
    // End of Misc event listener
    
    // Physical button event Listener
    $(document).on("backbutton", function(event) {
        var title = "SweetHome";
        var text = "Running in background";
        var ticker = "SweetHome is running in background";
        var enableExtraEffects = $('#vibrate-notification-toggle').is(":checked");
        var noOp = function() {};

        if (!isAuthenticated()) {
            presenter.exitApp();
            return;
        }

        presenter.sendStatusBarNotification(title, text, ticker, enableExtraEffects, function() {
            presenter.sendAppToBackground(noOp, noOp);
        }, 
        noOp);
    });                         

    $(document).on("menubutton", function(event) {
        if (isAuthenticated())
            $("#leftpanel").panel("toggle");
    });
    // End of Physical button event Listener

    // End of Event Listeners
    
    // Callback methods 
    function populateHomeData(item) { 
        $("#data-now-listview li:nth-child(1)").text("Temperature: " + item.temperature + " ℃");
        $("#data-now-listview li:nth-child(2)").text("Home Brightness: " + (item.brightness === 0 ? "OK" : "Too dim"));
        $("#data-now-listview li:nth-child(3)").text("Fire Safety: " + (item.firesafety === 0 ? "OK" : "Dangerous"));
        utils.hideLoader();
    }

    function populateHouseworkList(dataList) {
        var finalHtml = '';

        houseworkList = dataList;
        dataList.forEach(function(item, index, array) {
            var itemHtml = '<li><a class="ui-btn ui-btn-icon-right %STATUS_CLASS%" href=""><img src="%AVATAR%">%TASK%</a></li>\n';
            
            itemHtml = itemHtml
                    .replace('%STATUS_CLASS%', item.status === 1 ? 'ui-icon-check' : 'ui-icon-clock')
                    .replace('%AVATAR%', getImageUrl() + "/images/" + item.avatar)
                    .replace('%TASK%',item.task);

            finalHtml += itemHtml;
        });

        $("#housework-listview").empty().append(finalHtml).listview("refresh");
        utils.hideLoader();
    }

    function populateUserList(dataList) {
        var initOptionHtml = '<option value="0">All</option>\n';

        addUserOptions(dataList, initOptionHtml, "select#username");
        $("select#username").trigger("change");
    }

    function populateUsersForHouseworkCreation(dataList) {
        addUserOptions(dataList, "", "select#selectable-username");
        $("select#selectable-username").trigger("change");
        utils.hideLoader();
    }

    function showTemperatureStatsImg(dataList) {
        $("img#temp-trend-img").attr('src', getImageUrl() + "/images/" + dataList[0].graph);
        utils.hideLoader();
    }

    function populateBrightnessList(dataList) {
        populateStatisticsList(dataList, "ul#brightness-listview");
    }

    function populateFiresafetyList(dataList) {
        populateStatisticsList(dataList, "ul#firesafty-listview");
    }

    function populateSugarHistory(dataList) {
        var finalHtml = '';
        var sugarListHtml = '<li><a href="" class="ui-btn">\
                                <h2>%TIME%</h2> \
                                <p>%TAG%</p> \
                                <p class="ui-li-aside"><strong>%VALUE%</strong>&nbsp;mmol/L</p> \
                                </a> \
                             </li>';
        
        dataList.forEach(function(item, index, array) {
            finalHtml += sugarListHtml.replace('%TIME%', item.date + " " + item.time)
                                      .replace('%TAG%', getBloodSugarDescription(item.tag))
                                      .replace('%VALUE%', item.value)
        });

        $("ul#sugar-history-listview").empty().append(finalHtml).listview("refresh");
        $("ul#sugar-stats-datefield-listview li#sugar-stats-datefield").text("Date: " + utils.getCurrentDate());
        utils.hideLoader();
    }

    function showBloodSugarStatsImg(dataList) {
        $("img#sugar-stats-img").attr('src', getImageUrl() + "/images/" + dataList[0].graph);
    }
    
    function populateLocationTrackListview(dataList) {
        var finalHtml = '';
        var locationHtmlTemplate = '\
                            <li>\
                                <a href="">\
                                    <img src="%USER_AVATAR%" alt="">\
                                    <h2>%USER_NAME%</h2>\
                                    <p>%LOCATION_DESC%</p>\
                                    <p class="ui-li-aside"><strong>%TIME%</strong></p> \
                                </a>\
                            </li>';

        dataList.forEach(function(item, index, array) {
            finalHtml += locationHtmlTemplate.replace('%USER_AVATAR%', getImageUrl() + "/images/" + item.user_avatar)
                                             .replace('%USER_NAME%', item.user_name)
                                             .replace('%LOCATION_DESC%', item.location_desc)
                                             .replace('%TIME%', utils.extractTimeFromDatetime(item.time));
        });
        
        locationTrackList = dataList;
        $("ul#location-thumbnail-listview").empty().append(finalHtml).listview("refresh");
        utils.hideLoader();
    }

    function populateLocationDetailListview(dataList) {
        var finalHtml = '';
        var locationDetailListviewHtmlTemplae = '\
                                            <li>\
                                                <h2>%LOCATION_DESC%</h2>\
                                                <p>%TIME%</p>\
                                            </li>';
        
        dataList.forEach(function(item, index, array) {
            finalHtml += locationDetailListviewHtmlTemplae.replace('%LOCATION_DESC%', item.location_desc)
                                                          .replace('%TIME%', item.time);
        });

        utils.hideLoader();
        utils.navigateTo('#location-track-detail');
        $('ul#location-track-detail-listview').empty().append(finalHtml).listview("refresh");
    }

    function populateFileListview(fileList) {
        var finalHtml = '';
        var fileListviewHtmlTemplate = '\
                                    <tr> \
                                            <td><img class="file-type-img" src="%FILE_TYPE_IMAGE%" alt=""><a href="" file-id="%MYFILES_ITEM_INDEX%" data-ajax="false">%FILE_NAME%</a> \
                                    </tr> ';
        
        currentFileList = fileList;
        fileList.forEach(function(item, index, array) {
            finalHtml += fileListviewHtmlTemplate
                            .replace('%FILE_TYPE_IMAGE%', item.type === 0 ? "images/folder-64x64.png" : "images/file_9-64x64.png")
                            .replace('%FILE_NAME%', item.name)
                            .replace('%MYFILES_ITEM_INDEX%', index);
        });

        $('table#my-files-table').empty().append(finalHtml);

        // Add eventListener to the newly created link, it's very important.
        // What's more, we need to unbind the event at first, or there will be more and more
        // event handlers on this node.
        $('table#my-files-table tr td a').unbind('click');
        $('table#my-files-table tr td a').click(function (event) {
            var clickedFileItem = currentFileList[$(this).attr("file-id")];
            var clickedName = clickedFileItem.name;
            var clickedType = clickedFileItem.type;

            event.preventDefault();
            event.stopPropagation();

            utils.showLoader();
            if (clickedType === 0) {
                currentDirName += "/" + clickedName; 
                console.log(currentDirName);
                presenter.getFileList(currentDirName, populateFileListview);
            }
            else if (clickedType === 1) {
                presenter.downloadMyFile(currentDirName + "/" + clickedName, 
                                         clickedName, 
                                         function(entry) {
                                            utils.showToast("Download File Successfully.", 'short', 'bottom');
                                            utils.hideLoader();
                                         }),
                                         function(error) {
                                            alert("Error during download: " + error.code);
                                            utils.hideLoader();
                                         }
            }
        });
        
        // Add file path listener
        $('div#my-files-path a').unbind('click');
        $('div#my-files-path a').text(". . .")
                                .click(function(event) {
                                    event.preventDefault();
                                    event.stopPropagation();
                                    currentDirName = utils.extractUpDirPath(currentDirName);
                                    console.log(currentDirName);
                                    presenter.getFileList(currentDirName, populateFileListview);
                                });
        $('div#my-files-path span').text("     /     " + utils.extractItemOnPathFromLast(currentDirName, 1));                        
        utils.hideLoader();
    }

    function populateMyselfInfo(dataList) {
        var mydata = dataList[0];
        var userItemSelector = $('a#user-item');

        // Set current user model
        currentUser = mydata;

        userItemSelector.find("img").prop('src', getImageUrl() + '/images/' + mydata.avatar);
        userItemSelector.find("h2").text(mydata.name);
        userItemSelector.find("p").text(mydata.birth + " " + simpleSexMap[mydata.sex]);
    }

    function populateUserDetails(userData) {
        var userDetailsSelector = $('div#user-detail'); 
        
        userDetailsSelector.find('ul#user-detail-listview li#user-avatar-item img').prop('src', getImageUrl() + '/images/' + userData.avatar);
        userDetailsSelector.find('ul#user-detail-listview li#user-name-item span:nth-child(2)').text(userData.name);
        userDetailsSelector.find('ul#user-detail-listview li#user-email-item span:nth-child(2)').text(userData.email);
        userDetailsSelector.find('ul#user-noncrtitical-detail-listview li#user-gender-item span:nth-child(2)').text(fullSexMap[userData.sex]);
        userDetailsSelector.find('ul#user-noncrtitical-detail-listview li#user-birth-item span:nth-child(2)').text(userData.birth);
    }

    function populateUserListview(dataList) {
        var userListTemplate = ' \
                                <li user-id="%USER_ID%" data-icon="false"> \
                                    <a>\
                                        <img src="%AVATAR%" alt="avatar"> \
                                        <h2>%NAME% %ICON%</h2> \
                                        <p>%BIRTHDAY% %GENDER%</p>\
                                        <p><strong>%EMAIL%</strong></p>\
                                    </a>\
                                </li>';
        var memberListviewSelector = $('#my-family #member-listview');                        
        var resultHtml = '';

        dataList.forEach(function(item, index, array) {
            resultHtml += userListTemplate.replace('%AVATAR%', getImageUrl() + '/images/' + item.avatar)
                                          .replace('%USER_ID%', item.id)
                                          .replace('%NAME%', item.name)
                                          .replace('%BIRTHDAY%', item.birth)
                                          .replace('%GENDER%', simpleSexMap[item.sex])
                                          .replace('%EMAIL%', item.email)
                                          .replace('%ICON%', 0 === item.role ? '<i class="fa fa-user"></i>' : '');
        });

        memberListviewSelector.empty().append(resultHtml).listview("refresh");
    }

    function initApp() {
        // Init options from localStorage
        initLocalOptions();

        // Start the location tracking task
        sendLocationTask();

        // Init options from server
        presenter.getUserOptions(function (options) {
            options.forEach(function(element, index, array) {
                var key = utils.getKeyByValueFromObject(optionMap, element.key);

                if ($.inArray(key, checkableUI) > -1) {
                    try {
                        $(key).prop("checked", element.value === 'true').checkboxradio("refresh");
                    } catch (err) {
                        console.log(err);
                    }
                } else {
                    $(key).val(element.value);
                }
            });
        });
    }

    // End of callback methods

    // Helper methods
    function addUserOptions(dataList, initOptionHtml, selector) {
         var finalHtml = initOptionHtml;

         dataList.forEach(function(item, index, array) {
            var optionHtml = '<option value="%USER_ID%">%USER_NAME%</option>\n';

            optionHtml = optionHtml
                    .replace('%USER_ID%', item.id)
                    .replace('%USER_NAME%', item.name);
            
            finalHtml += optionHtml;
        });

        $(selector).empty().append(finalHtml);
    }

    function populateStatisticsList(dataList, selector) {
        var listItemHtml = '<li><a href="" class="ui-btn ui-btn-icon-right ui-icon-alert">%TIME%</a></li>';
        var finalHtml = '';

        dataList.forEach(function(item, index, array) {
            finalHtml += listItemHtml.replace("%TIME%", item.time);
        });

        $(selector).empty().append(finalHtml).listview("refresh");
    }

    function getBloodSugarDescription(tagNum) {
        var tagMap = {};

        tagMap[1] = "Before Breakfast";
        tagMap[2] = "After Breakfast";
        tagMap[3] = "Before Lunch";
        tagMap[4] = "After Lunch";
        tagMap[5] = "Before Dinner";
        tagMap[6] = "After Dinner";

        return tagMap[tagNum];
    }

    function sendLocationTask() {
        var isTrackMyLocationPermitted = $('#user-locationtrack-toggle').is(":checked");
        var isLivingInChina = $('#is-living-in-china-toggle').is(":checked") ? 1 : 0;
        var locationTrackInterval = 300000; // set initial interval to 5 mins

        console.log("[SweetHomeApp] track: " + isTrackMyLocationPermitted + " china: " + isLivingInChina);

        if (isTrackMyLocationPermitted) {
            console.log("Start reporting my location...");
            locationTrackInterval = $('#location-track-interval-select').val();
            presenter.reportMyLocation(isLivingInChina);
        }
        
        task = setTimeout(sendLocationTask, locationTrackInterval);
    }

    function saveOption(key, value) {
        if (utils.isStrEmpty(key) || utils.isStrEmpty(value))
            return;

        presenter.updateUserOption(key, value, function() {});    
    }

    function changePageTitle(pageSelector, label) {
        if (utils.isStrEmpty(pageSelector))
            return;

        $(pageSelector + " h1").text(label);
    }

    function getCurrentPageId() {
        var pageId = $('body').pagecontainer('getActivePage').prop('id');

        return pageId;
    }

    function getParamsMapFromUrl(url) {
        var paramsMap = {};

        if (utils.isStrEmpty(url))
            return paramsMap;
        
        var paramsStr = url.split('?')[1];

        if (utils.isStrEmpty(paramsStr))
            return paramsMap;

        var paramsPairNodes = paramsStr.split('&');

        paramsPairNodes.forEach(function(element, index, array) {
            var param = element.split('=');
            var name = param[0];
            var value = param[1];

            paramsMap[name] = value;
        });

        return paramsMap;
    }

    function setGenderDetail(genderItemSelector) {
        genderItemSelector.siblings().find('i').removeClass('fa-check-square-o').addClass('fa-square-o');
        genderItemSelector.find('i').removeClass('fa-square-o').addClass('fa-check-square-o');
    }

    function getImageUrl() {
        return window.isCordovaApp ? utils.appConfig().serverHost() : '..';
    }

    function isAuthenticated() {
         return !utils.isStrEmpty(utils.appConfig().accessTokenValue()); 
    }

    /**
     * Get options from localStorage and apply to UI respectively
     */
    function initLocalOptions() {
        for (var key in localStorage) {
            var value = localStorage.getItem(key);
            var selector = utils.getKeyByValueFromObject(optionMap, key);

            if (utils.isObjEmpty(selector))
                continue;
            
            if ($.inArray(selector, checkableUI) > -1) {
                try {
                    $(selector).prop("checked", value === 'true').flipswitch("refresh");
                } catch (err) {
                    console.debug(err);
                }
            }
            else {
                $(selector).val(value);
            }
        }
    }

    function loadDataOnDeviceready() {
        if (localStorage.getItem('system.usercenter.donotrememberlogin') === 'true') {
            return;
        }

        var username = localStorage.getItem('username');
        var password = localStorage.getItem('password');

        if (!utils.isStrEmpty(username) && !utils.isStrEmpty(password)) {
            $('#login-username-input').val(username);
            $('#login-password-input').val(password);
        }
    }

    function hiddenAdminOnlyEntries() {
        var adminOnlyFeatures = [
            '#my-family',
            '#location-track'
        ];
        
        adminOnlyFeatures.forEach(function(item, index, array) {
            $('#leftpanel a[href="' + item + '"]').addClass("hidden-block");
        });
    }

    function restoreToDefaultEntries() {
        $('#leftpanel a').removeClass("hidden-block");
    }

    /**
     * Clear texts in Jquery Mobile textinput
     * @param {JQuery} inputSelector the input object to clear
     */
    function clearInputTexts(inputSelector) {
        inputSelector.val('').trigger('keyup');
    }
    // End of Helper methods

    return function View() {
        this.preInit = loadDataOnDeviceready;
    };
});
